//
// Created by mabinjie on 2024/10/23.
//

#ifndef UTILS_HPP
#define UTILS_HPP
#include <iomanip>
#include <sstream>
#include <bitset>
#include <ranges>


namespace common {

inline std::string toHex(const void *memory, const size_t size=1) {
    std::stringstream ss;
    const auto* ptr = static_cast<const std::byte*>(memory);
    ss << std::hex << std::uppercase << std::setfill('0') << "0x";
    for(size_t i = 0; i < size; ++i) {
        ss << std::setw(2) << static_cast<int>(ptr[i]);
    }
    return ss.str();
}

template<size_t N>
std::string toBin(const void *memory) {
    const auto temp = static_cast<const unsigned*>(memory);
    std::bitset<N> bitset(*temp);
    return bitset.to_string();
}

inline std::string replace_all(std::string str, const std::string& from, const std::string& to) {
    size_t start_pos = 0;
    while((start_pos = str.find(from, start_pos)) != std::string::npos) {
        str.replace(start_pos, from.length(), to);
        start_pos += to.length(); // Move past the last replacement
    }
    return str;
}

inline std::vector<std::string> split(const std::string& str, const std::string& delimiter) {
    std::vector<std::string> tokens;
    auto range = str | std::views::split(delimiter)
             | std::views::transform([](auto&& v) {
                 return std::string(v.begin(), v.end());
             })
             | std::views::filter([](const std::string& s) {
                 return !s.empty();
             });

    std::ranges::copy(range, std::back_inserter(tokens));
    return tokens;
}

template<typename... Args, typename T>
T &get_first_arg(T &fist, Args...) {
    return fist;
}

template<typename... Args>
constexpr size_t count_args(Args... args) {
    return sizeof...(Args);
}

}

#endif //UTILS_HPP
